package com.lishui.waterojbackenduserservice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lishui.waterojbackendcommon.contant.MessageConstant;
import com.lishui.waterojbackendcommon.contant.UserConstant;
import com.lishui.waterojbackendcommon.exception.BusinessException;
import com.lishui.waterojbackendcommon.exception.ParameterException;
import com.lishui.waterojbackendcommon.exception.PermissionException;
import com.lishui.waterojbackendmodel.model.pojo.dto.UserLoginDTO;
import com.lishui.waterojbackendmodel.model.pojo.dto.UserRegisterDTO;
import com.lishui.waterojbackendmodel.model.pojo.dto.UserUpdateDTO;
import com.lishui.waterojbackendmodel.model.pojo.entity.User;
import com.lishui.waterojbackendmodel.model.pojo.vo.UserVO;
import com.lishui.waterojbackenduserservice.mapper.UserMapper;
import com.lishui.waterojbackenduserservice.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.lishui.waterojbackendcommon.contant.UserConstant.USER_LOGIN_STATE;


/**
 * 用户服务实现类
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Resource
    private UserMapper userMapper;


    /**
     * 用户注册
     * @return 新用户 id
     */
    @Override
    public long userRegister(UserRegisterDTO userRegisterDTO) {
        String userPassword = userRegisterDTO.getUserPassword();
        String userAccount = userRegisterDTO.getUserAccount();
        String checkPassword = userRegisterDTO.getCheckPassword();
        // 账户不能包含特殊字符
        String validPattern = "[`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        Matcher matcher = Pattern.compile(validPattern).matcher(userAccount);
        if (matcher.find()) {
            throw new ParameterException(MessageConstant.CONTAINS_SPECIAL_CHARACTERS);
        }
        // 密码和校验密码不相同
        if (!userPassword.equals(checkPassword)) {
            throw new ParameterException(MessageConstant.PASSWORD_DIFFER_CODE);
        }
        // 2. 加密
        String encryptPassword = DigestUtils.md5DigestAsHex((UserConstant.SALT + userPassword).getBytes());
        // 3. 插入数据
        User user = new User();
        BeanUtils.copyProperties(userRegisterDTO, user);
        user.setUserPassword(encryptPassword);
        boolean saveResult = this.save(user);
        if (!saveResult) {
            throw new BusinessException(MessageConstant.REGISTER_FAILED);
        }
        return user.getId();
    }

    /**
     * 用户登录
     */
    @Override
    public UserVO userLogin(UserLoginDTO userLoginDTO, HttpServletRequest request) {
        String userAccount = userLoginDTO.getUserAccount();
        String userPassword = userLoginDTO.getUserPassword();
        // 账户不能包含特殊字符
        String validPattern = "[`~!@#$%^&*()+=|{}':;',\\\\[\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        Matcher matcher = Pattern.compile(validPattern).matcher(userAccount);
        if (matcher.find()) {
            throw new ParameterException(MessageConstant.CONTAINS_SPECIAL_CHARACTERS);
        }
        // 2. 加密
        String encryptPassword = DigestUtils.md5DigestAsHex((UserConstant.SALT + userPassword).getBytes());
        // 查询用户是否存在
        QueryWrapper<User> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("user_account", userAccount);
        Long count = userMapper.selectCount(queryWrapper1);
        // 用户不存在
        if (count == 0) {
            throw new BusinessException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        // 查询密码是否正确
        QueryWrapper<User> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("user_account", userAccount);
        queryWrapper2.eq("user_password", encryptPassword);
        User user = userMapper.selectOne(queryWrapper2);
        // 密码错误
        if (user == null) {
            throw new BusinessException(MessageConstant.PASSWORD_ERROR);
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        // 3. 记录用户的登录态，用userId记录登录态
        request.getSession().setAttribute(USER_LOGIN_STATE, userVO.getId());
        return userVO;
    }

    /**
     * 用户退出登录
     *
     * @param request
     */
    @Override
    public void userLogout(HttpServletRequest request) {
        // 移除登录态
        request.getSession().removeAttribute(USER_LOGIN_STATE);
    }

    @Override
    public List<UserVO> searchUsers(String username) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(username)) {
            queryWrapper.like("username", username);
        }
        List<User> userList = userMapper.selectList(queryWrapper);
        return userList.stream().map(user -> {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user, userVO);
            return userVO;
        }).collect(Collectors.toList());
    }

    /**
     * 是否为管理员
     * @return
     */
    @Override
    public boolean isAdmin(Long userId) {
        User user = this.getById(userId);
        return user != null && user.getUserRole() == UserConstant.ADMIN_ROLE;
    }

    @Override
    public void update(UserUpdateDTO userUpdateDTO, HttpServletRequest httpServletRequest) {
        User user = new User();
        BeanUtils.copyProperties(userUpdateDTO, user);
        Long nowUserId = user.getId();
        if (nowUserId == null) throw new ParameterException(MessageConstant.USER_ID_EXCEPTION);
        // 鉴定权限，当为 管理员用户 或 当前用户 时允许修改
        UserVO currentUser = getCurrentUser(httpServletRequest);
        if(!Objects.equals(currentUser.getId(), nowUserId) && !isAdmin(currentUser.getId())) {
            throw new PermissionException(MessageConstant.MISSING_ADMINISTRATOR_RIGHTS);
        }
        String userPassword = user.getUserPassword();
        if (StringUtils.isNotBlank(userPassword)) {
            user.setUserPassword(DigestUtils.md5DigestAsHex((UserConstant.SALT + userPassword).getBytes()));
        }
        this.updateById(user);
    }

    @Override
    public UserVO getCurrentUser(HttpServletRequest request) {
        // 先判断是否已登录
        Long userId = (Long) request.getSession().getAttribute(USER_LOGIN_STATE);
        User currentUser = this.getById(userId);
        if (currentUser == null || currentUser.getId() == null) {
            throw new BusinessException(MessageConstant.USER_NOT_LOGIN);
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(currentUser, userVO);
        return userVO;
    }

}
